home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / ax25cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  18.7 KB  |  891 lines

  1. /*
  2. ** FILE: ax25cmd.c
  3. **
  4. ** AX.25 command handler.
  5. **
  6. ** 09/24/90 Bob Applegate, wa2zzx
  7. **    Added BCTEXT, BC, and BCINTERVAL commands for broadcasting an id
  8. **    string using UI frames.
  9. */
  10.  
  11. #include <stdio.h>
  12. #include "global.h"
  13. #include "config.h"
  14. #include "mbuf.h"
  15. #include "timer.h"
  16. #include "proc.h"
  17. #include "iface.h"
  18. #include "ax25.h"
  19. #include "lapb.h"
  20. #include "cmdparse.h"
  21. #include "socket.h"
  22. #include "mailbox.h"
  23. #include "session.h"
  24. #include "tty.h"
  25. #include "nr4.h"
  26. #include "commands.h"
  27.  
  28. static int axheard __ARGS((struct iface *ifp));
  29. static void axflush __ARGS((struct iface *ifp));
  30. static int doaxfilter __ARGS((int argc,char *argv[],void *p));
  31. static int doaxflush __ARGS((int argc,char *argv[],void *p));
  32. static int doaxirtt __ARGS((int argc,char *argv[],void *p));
  33. static int doaxkick __ARGS((int argc,char *argv[],void *p));
  34. static int doaxreset __ARGS((int argc,char *argv[],void *p));
  35. static int doaxroute __ARGS((int argc,char *argv[],void *p));
  36. static int doaxstat __ARGS((int argc,char *argv[],void *p));
  37. static int doaxwindow __ARGS((int argc,char *argv[],void *p));
  38. static int dobc __ARGS((int argc,char *argv[],void *p));
  39. static int dobcint __ARGS((int argc,char *argv[],void *p));
  40. static int dobctext __ARGS((int argc,char *argv[],void *p));
  41. static int doblimit __ARGS((int argc,char *argv[],void *p));
  42. static int dodigipeat __ARGS((int argc,char *argv[],void *p));
  43. static int domaxframe __ARGS((int argc,char *argv[],void *p));
  44. static int domycall __ARGS((int argc,char *argv[],void *p));
  45. static int don2 __ARGS((int argc,char *argv[],void *p));
  46. static int dopaclen __ARGS((int argc,char *argv[],void *p));
  47. static int dopthresh __ARGS((int argc,char *argv[],void *p));
  48. static int doaxtype __ARGS((int argc,char *argv[],void *p));
  49. static int dot3 __ARGS((int argc,char *argv[],void *p));
  50. static int dot4 __ARGS((int argc,char *argv[],void *p));
  51. static int doversion __ARGS((int argc,char *argv[],void *p));
  52. static void ax_bc __ARGS((struct iface *axif));
  53. static int axdest __ARGS((struct iface *ifp));
  54. extern struct lq *al_lookup __ARGS((struct iface *ifp,char *addr,int sort));
  55.  
  56. extern int axheard_filter_flag;        /* in axlink.c */
  57.  
  58. /* Default broadcast 'to' address in shifted ASCII */
  59. char ax_bcto[AXALEN] = {
  60.     'I'<<1, 'D'<<1, ' '<<1, ' '<<1, ' '<<1, ' '<<1, ('0'<<1) | E
  61. };
  62.  
  63. /* Defaults for IDing... */
  64. char *axbctext = NULL;    /* Text to send */
  65. static struct timer Broadtimer;    /* timer for broadcasts */
  66.  
  67. char *Ax25states[] = {
  68.     "",
  69.     "Disconnected",
  70.     "Listening",
  71.     "Conn pending",
  72.     "Disc pending",
  73.     "Connected",
  74.     "Recovery",
  75. };
  76.  
  77. /* Ascii explanations for the disconnect reasons
  78.    listed in lapb.h under "reason" in ax25_cb */
  79. char *Axreasons[] = {
  80.     "Normal",
  81.     "DM received",
  82.     "Timeout"
  83. };
  84.  
  85. static struct cmds Axcmds[] = {
  86.     "bc",        dobc,        0, 0, NULLCHAR,
  87.     "bcinterval",    dobcint,    0, 0, NULLCHAR,
  88.     "bctext",    dobctext,    0, 0, NULLCHAR,
  89.     "blimit",    doblimit,    0, 0, NULLCHAR,
  90.     "destlist",    doaxdest,    0, 0, NULLCHAR,
  91.     "digipeat",    dodigipeat,    0, 0, NULLCHAR,
  92.     "filter",    doaxfilter,    0, 0, NULLCHAR,
  93.     "flush",    doaxflush,    0, 0, NULLCHAR,
  94.     "heardlist",    doaxheard,    0, 0, NULLCHAR,
  95.     "irtt",        doaxirtt,    0, 0, NULLCHAR,
  96.     "kick",        doaxkick,    0, 2, "ax25 kick <axcb>",
  97.     "maxframe",    domaxframe,    0, 0, NULLCHAR,
  98.     "mycall",    domycall,    0, 0, NULLCHAR,
  99.     "paclen",    dopaclen,    0, 0, NULLCHAR,
  100.     "pthresh",    dopthresh,    0, 0, NULLCHAR,
  101.     "reset",    doaxreset,    0, 2, "ax25 reset <axcb>",
  102.     "retry",    don2,        0, 0, NULLCHAR,
  103.     "route",    doaxroute,    0, 0, NULLCHAR,
  104.     "status",    doaxstat,    0, 0, NULLCHAR,
  105.     "t3",        dot3,        0, 0, NULLCHAR,
  106.     "t4",        dot4,        0, 0, NULLCHAR,
  107.     "timertype",    doaxtype,    0, 0, NULLCHAR,
  108.     "version",    doversion,    0, 0, NULLCHAR,
  109.     "window",    doaxwindow,    0, 0, NULLCHAR,
  110.     NULLCHAR,
  111. };
  112.  
  113. /* Multiplexer for top-level ax25 command */
  114. int
  115. doax25(argc,argv,p)
  116. int argc;
  117. char *argv[];
  118. void *p;
  119. {
  120.     if(argc == 1)
  121.         return doaxheard(argc,argv,p);
  122.     return subcmd(Axcmds,argc,argv,p);
  123. }
  124.  
  125. /* This function is called to send the current
  126.    broadcast message and reset the timer. */
  127. static int dobc(argc,argv,p)
  128. int argc;
  129. char *argv[];
  130. void *p;
  131. {
  132.     struct iface *ifa;
  133.  
  134.     if (argc < 2) {
  135.         tprintf("you need to specify an interface\n");
  136.         return 0;
  137.     }
  138.  
  139.     ifa = Ifaces;
  140.     while (ifa != NULL && stricmp(ifa->name,argv[1]))
  141.         ifa = ifa->next;
  142.     if (ifa == NULL)
  143.         tprintf(Badinterface, argv[1]);
  144.     else if (ifa->type != TYPE_AX25)
  145.         tprintf("not an AX.25 interface\n");
  146.     else {
  147.         ax_bc(ifa);
  148.         stop_timer(&Broadtimer) ;    /* in case it's already running */
  149.         start_timer(&Broadtimer);    /* and fire it up */
  150.     }
  151. }
  152.  
  153. /* View/Change the message we broadcast. */
  154. static int dobctext(argc,argv,p)
  155. int argc;
  156. char *argv[];
  157. void *p;
  158. {
  159.     if (argc < 2)
  160.         tprintf("Broadcast text:\n %s\n",axbctext);
  161.     else {
  162.         if (axbctext != NULL) free(axbctext);
  163.         axbctext = malloc(strlen(argv[1]));
  164.         strcpy(axbctext,argv[1]);
  165.     }
  166.     return 0;
  167. }
  168.  
  169. #define TICKSPERSEC    (1000L / MSPTICK)    /* Ticks per second */
  170.  
  171. /* Examine/change the broadcast interval. */
  172. static int dobcint(argc,argv,p)
  173. int argc;
  174. char *argv[];
  175. void *p;
  176. {
  177.     void dobroadtick();
  178.  
  179.     if(argc < 2) {
  180.         tprintf("Broadcast timer %lu/%lu seconds\n",
  181.             read_timer(&Broadtimer)/TICKSPERSEC,
  182.             dur_timer(&Broadtimer)/TICKSPERSEC);
  183.         return 0;
  184.     }
  185.     stop_timer(&Broadtimer) ;    /* in case it's already running */
  186.     Broadtimer.func = (void (*)())dobroadtick;/* what to call on timeout */
  187.     Broadtimer.arg = NULLCHAR;        /* dummy value */
  188.     Broadtimer.start = atoi(argv[1])*TICKSPERSEC;    /* set timer duration */
  189.     start_timer(&Broadtimer);        /* and fire it up */
  190.     return 0;
  191. }
  192.  
  193. void dobroadtick()
  194. {
  195.     struct iface *ifa;
  196.  
  197.     ifa = Ifaces;
  198.  
  199.     while (ifa != NULL) {
  200.         if (ifa->type == TYPE_AX25) ax_bc(ifa);
  201.         ifa = ifa->next;
  202.     }
  203.  
  204.     /* Restart timer */
  205.     start_timer(&Broadtimer) ;
  206. }
  207.  
  208. /* This is the low-level broadcast function. */
  209. static void ax_bc(axif)
  210. struct iface *axif;
  211. {
  212.     struct mbuf *hbp;
  213.     int16 i;
  214.  
  215.     /* prepare the header */
  216.     i = strlen(axbctext);
  217.     if((hbp = alloc_mbuf(i)) == NULLBUF)
  218.         return;
  219.  
  220.     hbp->cnt = i;
  221.     memcpy(hbp->data,axbctext,i);
  222.  
  223.     (*axif->output)(axif, ax_bcto, axif->hwaddr,
  224.         PID_NO_L3, hbp);    /* send it */
  225.  
  226.     /*
  227.     ** Call another function to reset the timer...
  228.     reset_bc_timer();
  229.     */
  230. }
  231.  
  232. int doaxheard(argc,argv,p)
  233. int argc;
  234. char *argv[];
  235. void *p;
  236. {
  237.     struct iface *ifp;
  238.  
  239.     if(argc > 1) {
  240.         if((ifp = if_lookup(argv[1])) == NULLIF) {
  241.             tprintf(Badinterface, argv[1]);
  242.             return 1;
  243.         }
  244.         if(ifp->output != ax_output) {
  245.             tprintf("Interface %s not AX.25\n",argv[1]);
  246.             return 1;
  247.         }
  248.         axheard(ifp);
  249.         return 0;
  250.     }
  251.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next) {
  252.         if(ifp->output != ax_output)
  253.             continue;    /* Not an ax.25 interface */
  254.         if(axheard(ifp) == EOF)
  255.             break;
  256.     }
  257.     return 0;
  258. }
  259.  
  260. static int axheard(ifp)
  261. struct iface *ifp;
  262. {
  263.     int col = 0;
  264.     struct lq *lp;
  265.     char tmp[AXBUF];
  266.  
  267.     if(ifp->hwaddr == NULLCHAR)
  268.         return 0;
  269.  
  270.     tprintf("Interface  Station   Time since send  Pkts sent\n");
  271.     tprintf("%-9s  %-9s   %12s    %7lu\n",ifp->name,pax25(tmp,ifp->hwaddr),
  272.      tformat(Clock - ifp->lastsent),ifp->rawsndcnt);
  273.  
  274.     tprintf("Station       Last Heard       Pkts  : ");
  275.     tprintf("Station       Last Heard       Pkts\n");
  276.     for(lp = Lq;lp != NULLLQ;lp = lp->next) {
  277.         if(lp->iface != ifp)
  278.             continue;
  279.         if(col)
  280.             tprintf("  : ");
  281.         if(tprintf("%-9s   %12s    %7lu",pax25(tmp,lp->addr),
  282.          tformat(Clock - lp->time),lp->currxcnt) == EOF)
  283.             return EOF;
  284.         if(col) {
  285.             if(tprintf("\x0f\n") == EOF) {
  286.                 return EOF;
  287.             } else col = 0;
  288.         } else col = 1;
  289.     }
  290.     if(col)
  291.         tprintf("\n");
  292.     return 0;
  293. }
  294.  
  295. int doaxdest(argc,argv,p)
  296. int argc;
  297. char *argv[];
  298. void *p;
  299. {
  300.     struct iface *ifp;
  301.  
  302.     if(argc > 1){
  303.         if((ifp = if_lookup(argv[1])) == NULLIF){
  304.             tprintf(Badinterface,argv[1]);
  305.             return 1;
  306.         }
  307.         if(ifp->output != ax_output){
  308.             tprintf("Interface %s not AX.25\n",argv[1]);
  309.             return 1;
  310.         }
  311.         axdest(ifp);
  312.         return 0;
  313.     }
  314.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  315.         if(ifp->output != ax_output)
  316.             continue;    /* Not an ax.25 interface */
  317.         if(axdest(ifp) == EOF)
  318.             break;
  319.     }
  320.     return 0;
  321. }
  322.  
  323. static int axdest(ifp)
  324. struct iface *ifp;
  325. {
  326.     struct ld *lp;
  327.     struct lq *lq;
  328.     char tmp[AXBUF];
  329.  
  330.     if(ifp->hwaddr == NULLCHAR)
  331.         return 0;
  332.     tprintf("%s:\n",ifp->name);
  333.     tprintf("Station   Last ref         Last heard           Pkts\n");
  334.     for(lp = Ld;lp != NULLLD;lp = lp->next){
  335.         if(lp->iface != ifp)
  336.             continue;
  337.  
  338.         tprintf("%-10s%-17s",
  339.          pax25(tmp,lp->addr),tformat(Clock - lp->time));
  340.  
  341.         if(addreq(lp->addr,ifp->hwaddr)){
  342.             /* Special case; it's our address */
  343.             tprintf("%-17s",tformat(Clock - ifp->lastsent));
  344.         } else if((lq = al_lookup(ifp,lp->addr,0)) == NULLLQ){
  345.             tprintf("%-17s","");
  346.         } else {
  347.             tprintf("%-17s",tformat(Clock - lq->time));
  348.         }
  349.         if(tprintf("%8lu\n",lp->currxcnt) == EOF)
  350.             return EOF;
  351.     }
  352.     return 0;
  353. }
  354.  
  355. static int doaxfilter(argc,argv,p)
  356. int argc;
  357. char *argv[];
  358. void *p;
  359. {
  360.     if(argc >= 2){
  361.         setint(&axheard_filter_flag,"ax25 heard filter",argc,argv);
  362.     } else {
  363.         tprintf("Usage: ax25 filter <0|1|2|3>\n");
  364.         return 1;
  365.     }
  366.  
  367.     tprintf("Callsign logging by source ");
  368.     if(axheard_filter_flag & AXHEARD_NOSRC)
  369.         tprintf("disabled, ");
  370.     else
  371.         tprintf("enabled, ");
  372.     tprintf("by destination ");
  373.     if(axheard_filter_flag & AXHEARD_NODST)
  374.         tprintf("disabled\n");
  375.     else
  376.         tprintf("enabled\n");
  377.     return 0;
  378. }
  379.  
  380. static int doaxflush(argc,argv,p)
  381. int argc;
  382. char *argv[];
  383. void *p;
  384. {
  385.     struct iface *ifp;
  386.  
  387.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  388.         if(ifp->output != ax_output)
  389.             continue;    /* Not an ax.25 interface */
  390.         axflush(ifp);
  391.     }
  392.     return 0;
  393. }
  394.  
  395. static void axflush(ifp)
  396. struct iface *ifp;
  397. {
  398.     struct lq *lp,*lp1;
  399.     struct ld *ld,*ld1;
  400.  
  401.     ifp->rawsndcnt = 0;
  402.     for(lp = Lq;lp != NULLLQ;lp = lp1){
  403.         lp1 = lp->next;
  404.         free((char *)lp);
  405.     }
  406.     Lq = NULLLQ;
  407.  
  408.     for(ld = Ld;ld != NULLLD;ld = ld1){
  409.         ld1 = ld->next;
  410.         free((char *)ld);
  411.     }
  412.     Ld = NULLLD;
  413. }
  414.  
  415. static doaxreset(argc,argv,p)
  416. int argc;
  417. char *argv[];
  418. void *p;
  419. {
  420.     struct ax25_cb *axp;
  421.  
  422.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  423.     if(!ax25val(axp)){
  424.         tprintf(Notval);
  425.         return 1;
  426.     }
  427.     reset_ax25(axp);
  428.     return 0;
  429. }
  430.  
  431. /* Display AX.25 link level control blocks */
  432. static doaxstat(argc,argv,p)
  433. int argc;
  434. char *argv[];
  435. void *p;
  436. {
  437.     register int i;
  438.     register struct ax25_cb *axp;
  439.     char tmp[AXBUF];
  440.  
  441.     if(argc < 2){
  442.         tprintf("    &AXB Snd-Q   Rcv-Q   Remote    State\n");
  443.         for(i=0;i<NHASH;i++){
  444.             for(axp = Ax25_cb[i];axp != NULLAX25; axp = axp->next){
  445.  
  446.                 if(tprintf("%8lx %-8d%-8d%-10s%s\n",
  447.                     ptol(axp),
  448.                     len_q(axp->txq),len_p(axp->rxq),
  449.                     pax25(tmp,axp->remote),
  450.                     Ax25states[axp->state]) == EOF)
  451.                         return 0;
  452.             }
  453.         }
  454.         return 0;
  455.     }
  456.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  457.     if(!ax25val(axp)){
  458.         tprintf(Notval);
  459.         return 1;
  460.     }
  461.     st_ax25(axp);
  462.     return 0;
  463. }
  464.  
  465. /* Dump one control block */
  466. void st_ax25(axp)
  467. register struct ax25_cb *axp;
  468. {
  469.     char tmp[AXBUF];
  470.  
  471.     if(axp == NULLAX25)
  472.         return;
  473.     tprintf("    &AXB Remote   RB V(S) V(R) Unack P Retry State\n");
  474.  
  475.     tprintf("%8lx %-9s%c%c",ptol(axp),pax25(tmp,axp->remote),
  476.      axp->flags.rejsent ? 'R' : ' ',
  477.      axp->flags.remotebusy ? 'B' : ' ');
  478.     tprintf(" %4d %4d",axp->vs,axp->vr);
  479.     tprintf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
  480.     tprintf(" %02u/%02u",axp->retries,axp->n2);
  481.     tprintf(" %s\n",Ax25states[axp->state]);
  482.  
  483.     tprintf("SRTT = %lu MDEV = %lu ",axp->srt,axp->mdev);
  484.     tprintf("T1: ");
  485.     if(run_timer(&axp->t1))
  486.         tprintf("%lu",read_timer(&axp->t1) * MSPTICK);
  487.     else
  488.         tprintf("stop");
  489.     tprintf("/%lu ms; ",dur_timer(&axp->t1) * MSPTICK);
  490.  
  491.     tprintf("T3: ");
  492.     if(run_timer(&axp->t3))
  493.         tprintf("%lu",read_timer(&axp->t3) * MSPTICK);
  494.     else
  495.         tprintf("stop");
  496.     tprintf("/%lu ms; ",dur_timer(&axp->t3) * MSPTICK);
  497.  
  498.     tprintf("T4: ");
  499.     if(run_timer(&axp->t4))
  500.         tprintf("%lu",(read_timer(&axp->t4) * MSPTICK) / 1000);
  501.     else
  502.         tprintf("stop");
  503.     tprintf("/%lu sec\n",(dur_timer(&axp->t4) * MSPTICK) / 1000);
  504. }
  505.  
  506. /* Display or change our AX.25 address */
  507. static domycall(argc,argv,p)
  508. int argc;
  509. char *argv[];
  510. void *p;
  511. {
  512.     char tmp[AXBUF];
  513.  
  514.     if(argc < 2){
  515.         tprintf("%s\n",pax25(tmp,Mycall));
  516.         return 0;
  517.     }
  518.     if(setcall(Mycall,argv[1]) == -1)
  519.         return -1;
  520.     return 0;
  521. }
  522.  
  523. /* Control AX.25 digipeating */
  524. static dodigipeat(argc,argv,p)
  525. int argc;
  526. char *argv[];
  527. void *p;
  528. {
  529.     return setbool(&Digipeat,"Digipeat",argc,argv);
  530. }
  531.  
  532. /* Set limit on retransmission backoff */
  533. static doblimit(argc,argv,p)
  534. int argc;
  535. char *argv[];
  536. void *p;
  537. {
  538.     return setlong(&Blimit,"blimit",argc,argv);
  539. }
  540.  
  541. static doversion(argc,argv,p)
  542. int argc;
  543. char *argv[];
  544. void *p;
  545. {
  546.     return setshort(&Axversion,"AX25 version",argc,argv);
  547. }
  548.  
  549. static doaxirtt(argc,argv,p)
  550. int argc;
  551. char *argv[];
  552. void *p;
  553. {
  554.     return setlong(&Axirtt,"Initial RTT (ms)",argc,argv);
  555. }
  556.  
  557. /* Set idle timer */
  558. static dot3(argc,argv,p)
  559. int argc;
  560. char *argv[];
  561. void *p;
  562. {
  563.     return setlong(&T3init,"Idle poll timer (ms)",argc,argv);
  564. }
  565.  
  566. /* Set link redundancy timer */
  567. static dot4(argc,argv,p)
  568. int argc;
  569. char *argv[];
  570. void *p;
  571. {
  572.     return setlong(&T4init,"Link redundancy timer (sec)",argc,argv);
  573. }
  574.  
  575. /* Set retry limit count */
  576. static don2(argc,argv,p)
  577. int argc;
  578. char *argv[];
  579. void *p;
  580. {
  581.     return setshort(&N2,"Retry limit",argc,argv);
  582. }
  583.  
  584. /* Force a retransmission */
  585. static doaxkick(argc,argv,p)
  586. int argc;
  587. char *argv[];
  588. void *p;
  589. {
  590.     struct ax25_cb *axp;
  591.  
  592.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  593.     if(!ax25val(axp)){
  594.         tprintf(Notval);
  595.         return 1;
  596.     }
  597.     kick_ax25(axp);
  598.     return 0;
  599. }
  600.  
  601. /* Set maximum number of frames that will be allowed in flight */
  602. static domaxframe(argc,argv,p)
  603. int argc;
  604. char *argv[];
  605. void *p;
  606. {
  607.     return setshort(&Maxframe,"Window size (frames)",argc,argv);
  608. }
  609.  
  610. /* Set maximum length of I-frame data field */
  611. static dopaclen(argc,argv,p)
  612. int argc;
  613. char *argv[];
  614. void *p;
  615. {
  616.     return setshort(&Paclen,"Max frame length (bytes)",argc,argv);
  617. }
  618.  
  619. /* Set size of I-frame above which polls will be sent after a timeout */
  620. static dopthresh(argc,argv,p)
  621. int argc;
  622. char *argv[];
  623. void *p;
  624. {
  625.     return setshort(&Pthresh,"Poll threshold (bytes)",argc,argv);
  626. }
  627.  
  628. /* Set high water mark on receive queue that triggers RNR */
  629. static doaxwindow(argc,argv,p)
  630. int argc;
  631. char *argv[];
  632. void *p;
  633. {
  634.     return setshort(&Axwindow,"AX25 receive window (bytes)",argc,argv);
  635. }
  636. /* End of ax25 subcommands */
  637.  
  638. /* Initiate interactive AX.25 connect to remote station */
  639. int doconnect(argc,argv,p)
  640. int argc;
  641. char *argv[];
  642. void *p;
  643. {
  644.     struct sockaddr_ax fsocket;
  645.     struct session *sp;
  646.     int ndigis,i;
  647.     char digis[MAXDIGIS][AXALEN];
  648.     char target[AXALEN];
  649.  
  650.     if(setcall(target,argv[2]) == -1){
  651.         tprintf("Bad callsign %s\n", argv[2]);
  652.         return 1;
  653.     }
  654.  
  655.     /* If digipeaters are given, put them in the routing table */
  656.     if(argc > 3){
  657.         if(setcall(target,argv[2]) == -1){
  658.             tprintf("Bad callsign %s\n", argv[2]);
  659.             return 1;
  660.         }
  661.         ndigis = argc - 3;
  662.         if(ndigis > MAXDIGIS){
  663.             tprintf("Too many digipeaters\n");
  664.             return 1;
  665.         }
  666.         for(i=0;i<ndigis;i++){
  667.             if(setcall(digis[i],argv[i+3]) == -1){
  668.                 tprintf("Bad digipeater %s\n",argv[i+3]);
  669.                 return 1;
  670.             }
  671.         }
  672.         if(ax_add(target,AX_LOCAL,digis,ndigis) == NULLAXR){
  673.             tprintf("Route add failed\n");
  674.             return 1;
  675.         }
  676.     }
  677.     /* Allocate a session descriptor */
  678.     if((sp = newsession(argv[2],AX25TNC)) == NULLSESSION){
  679.         tprintf("Too many sessions\n");
  680.         return 1;
  681.     }
  682.     if((sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
  683.         tprintf("Can't create socket\n");
  684.         freesession(sp);
  685.         keywait(NULLCHAR,1);
  686.         return 1;
  687.     }
  688.     fsocket.sax_family = AF_AX25;
  689.     setcall(fsocket.ax25_addr,argv[2]);
  690.     strncpy(fsocket.iface,argv[1],ILEN);
  691.     return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_ax));
  692. }
  693.  
  694. /* Display and modify AX.25 routing table */
  695. static int doaxroute(argc,argv,p)
  696. int argc;
  697. char *argv[];
  698. void *p;
  699. {
  700.     char tmp[AXBUF];
  701.     int i,j,ndigis;
  702.     register struct ax_route *axr;
  703.     char target[AXALEN],digis[MAXDIGIS][AXALEN];
  704.  
  705.     if(argc < 2){
  706.         tprintf("Target    Type  Mode Digipeaters\n");
  707.         for(i=0;i<NHASH;i++){
  708.             for(axr = Ax_routes[i];axr != NULLAXR;axr = axr->next){
  709.                 tprintf("%-10s%-6s",pax25(tmp,axr->target),
  710.                     axr->type == AX_LOCAL ? "Local":"Auto");
  711.                 switch(axr->mode){
  712.                 case AX_VC_MODE:
  713.                     tprintf(" VC ");
  714.                     break;
  715.                 case AX_DATMODE:
  716.                     tprintf(" DG ");
  717.                     break;
  718.                 case AX_DEFMODE:
  719.                     tprintf(" IF ");
  720.                     break;
  721.                 default:
  722.                     tprintf(" ?? ");
  723.                     break;
  724.                 }
  725.                 for(j=0;j<axr->ndigis;j++){
  726.                     tprintf(" %s",pax25(tmp,axr->digis[j]));
  727.                 }
  728.                 if(tprintf("\n") == EOF)
  729.                     return 0;
  730.             }
  731.         }
  732.         return 0;
  733.     }
  734.     if(argc < 3){
  735.         tprintf("Usage: ax25 route add <target> [digis...]\n");
  736.         tprintf("       ax25 route drop <target>\n");
  737.         tprintf("       ax25 route mode <target> [mode]\n");
  738.         return 1;
  739.     }
  740.     if(setcall(target,argv[2]) == -1){
  741.         tprintf("Bad target %s\n",argv[2]);
  742.         return 1;
  743.     }
  744.     switch(argv[1][0]){
  745.     case 'a':    /* Add route */
  746.         ndigis = argc - 3;
  747.         if(ndigis > MAXDIGIS){
  748.             tprintf("Too many digipeaters\n");
  749.             return 1;
  750.         }
  751.         for(i=0;i<ndigis;i++){
  752.             if(setcall(digis[i],argv[i+3]) == -1){
  753.                 tprintf("Bad digipeater %s\n",argv[i+3]);
  754.                 return 1;
  755.             }
  756.         }
  757.         if(ax_add(target,AX_LOCAL,digis,ndigis) == NULLAXR){
  758.             tprintf("Failed\n");
  759.             return 1;
  760.         }
  761.         break;
  762.     case 'd':    /* Drop route */
  763.         if(ax_drop(target) == -1){
  764.             tprintf("Not in table\n");
  765.             return 1;
  766.         }
  767.         break;
  768.     case 'm':    /* Alter route mode */
  769.         if(argc < 4){
  770.             tprintf("Usage: ax25 route mode <target> <mode>\n");
  771.             tprintf("Where mode is 'vc', 'datagram' or 'interface'\n");
  772.             return 1;
  773.         }
  774.         if((axr = ax_lookup(target)) == NULLAXR){
  775.             tprintf("Not in table\n");
  776.             return 1;
  777.         }
  778.         switch(argv[3][0]){
  779.         case 'i':    /* use default interface mode */
  780.             axr->mode = AX_DEFMODE;
  781.             break;
  782.         case 'v':    /* use virtual circuit mode */
  783.             axr->mode = AX_VC_MODE;
  784.             break;
  785.         case 'd':    /* use datagram mode */
  786.             axr->mode = AX_DATMODE;
  787.             break;
  788.         default:
  789.             tprintf("Unknown mode %s\n", argv[3]);
  790.             return 1;
  791.         }
  792.         break;
  793.     default:
  794.         tprintf("Unknown command %s\n",argv[1]);
  795.         return 1;
  796.     }
  797.     return 0;
  798. }
  799.  
  800. #ifdef    MAILBOX
  801. int ax25start(argc,argv,p)
  802. int argc;
  803. char *argv[];
  804. void *p;
  805. {
  806.     int s,type;
  807.  
  808.     freeargs(argc,argv);    /* Args are not used */
  809.     if (Axi_sock != -1)
  810.         return 0;
  811.  
  812.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  813.     chname(Curproc,"AX25 listener");
  814.     Axi_sock = socket(AF_AX25,SOCK_STREAM,0);
  815.     /* bind() is done automatically */
  816.     if(listen(Axi_sock,1) == -1){
  817.         close_s(Axi_sock);
  818.         return -1;
  819.     }
  820.     for(;;){
  821.         if((s = accept(Axi_sock,NULLCHAR,NULLINT)) == -1)
  822.             break;    /* Service is shutting down */
  823.  
  824.         type = AX25TNC;
  825.         /* Eat the line that triggered the connection
  826.          * and then start the mailbox
  827.          */
  828.         recvline(s,NULLCHAR,80); 
  829.         newproc("mbox",2048,mbx_incom,s,(void *)&type,NULL);
  830.     }
  831.     close_s(Axi_sock);
  832.     Axi_sock = -1;
  833.     return 0;
  834. }
  835.  
  836. int ax250(argc,argv,p)
  837. int argc;
  838. char *argv[];
  839. void *p;
  840. {
  841.     close_s(Axi_sock);
  842.     Axi_sock = -1;
  843.     return 0;
  844. }
  845. #endif
  846.  
  847. /* ax25 timers type - linear v exponential */
  848. static doaxtype(argc,argv,p)
  849. int argc ;
  850. char *argv[] ;
  851. void *p ;
  852. {
  853.     extern unsigned lapbtimertype;
  854.  
  855.     if (argc < 2) {
  856.         tprintf("AX25 timer type is ");
  857.         switch(lapbtimertype){
  858.         case 2:
  859.             tprintf("original\n");
  860.             break;
  861.         case 1:
  862.             tprintf("linear\n");
  863.             break;
  864.         case 0:
  865.             tprintf("exponential\n");
  866.             break;
  867.         }
  868.         return 0 ;
  869.     }
  870.     
  871.     switch (argv[1][0]) {
  872.         case 'o':
  873.         case 'O':
  874.             lapbtimertype = 2 ;
  875.             break ;
  876.         case 'l':
  877.         case 'L':
  878.             lapbtimertype = 1 ;
  879.             break ;
  880.         case 'e':
  881.         case 'E':
  882.             lapbtimertype = 0 ;
  883.             break ;
  884.         default:
  885.             tprintf("use: ax25 timertype [original|linear|exponential]\n") ;
  886.             return -1 ;
  887.     }
  888.  
  889.     return 0 ;
  890. }
  891.